Skip to content

arm: hisilicon: add hi3516cv200 / hi3518ev20x SoC support (CRG + DT + Kconfig)#43

Merged
widgetii merged 3 commits into
upstream-patchesfrom
feat/cv200-mainline
May 18, 2026
Merged

arm: hisilicon: add hi3516cv200 / hi3518ev20x SoC support (CRG + DT + Kconfig)#43
widgetii merged 3 commits into
upstream-patchesfrom
feat/cv200-mainline

Conversation

@widgetii
Copy link
Copy Markdown
Member

Summary

Adds first-class support for the V2 generation HiSilicon camera SoC family — Hi3516CV200, Hi3518EV200, Hi3518EV201 (ARM926EJ-S, ARMv5TE) — to the openipc/linux upstream-patches base. Mirrors the structure of #42 (cv300) so V2 and V3 share the same shape: CRG driver + DT + ARCH Kconfig, all keyed by sibling-compatible strings so the vendor 4.9 BSP DT is drop-in compatible with this driver.

Three commits, each independent:

  1. clk: hisilicon: add hi3516cv200 / hi3518ev20x CRG driver — port of the vendor 4.9 BSP `clk-hi3518ev20x.c` onto the modern crg- platform_driver scaffold. 25 fixed-rate roots, 5 muxes, 1 divider, 13 gates, 4 sysctrl timer muxes. Two `CLK_OF_DECLARE` entries make TIMER/APB/UART/ETH available before the platform_driver model is alive, identical to the SP804 / FEMAC pre-probe workaround landed for cv300.
  2. arm: dts: hisilicon: add hi3516cv200 SoC and DEMB board — ported from the vendor BSP `hi3518ev20x.dtsi`, scrubbed for 7.x: drops removed `skeleton.dtsi`, adds `clock-frequency = <3000000>` on SP804, `clock-names = "mdio"` on the hisi-femac-mdio node, `hisilicon,phy-reset-delays-us` on the femac.
  3. arm: hibvt: add ARCH_HI3516CV200 Kconfig entry — gates the option on `ARCH_MULTI_V5 + CPU_LITTLE_ENDIAN`, selects dependencies. Mirrors ARCH_HI3516CV300.

Test plan

Boots end-to-end under `qemu-system-arm -M hi3516cv200` (qemu-hisilicon master, machine model added previously), kernel pulled via this branch + nightly hi3516cv200 rootfs (vendor blob .ko load deliberately stubbed; that's an openhisilicon-side concern, not a kernel-side blocker):

  • SP804 clock initializes (no `clk_get_rate=0`)
  • PL011 console reaches `Welcome to OpenIPC`
  • `openipc-hi3516cv200 login:` prompt appears
  • No `Oops:`, `panic:`, `BUG:`, `Call Trace`, or `Unable to handle` on console
  • FEMAC reset controller succeeds (no `-EINVAL` from `reset_control_get`)
  • DHCP obtains lease via udhcpc — `eth0: 10.0.2.15/24` from QEMU SLIRP
  • Userspace init.d chain runs to completion (S99 probe fires)

Stage-2 hardware verification on a real Hi3516CV200 board is gated on the firmware-side PR that bundles this kernel with the new OSAL-shim module from openhisilicon — separate PR.

Companion PRs

  • OpenIPC/openhisilicon (cv200 OSAL shim module + source-side compat patches for 15 cv200 drivers using the same `kernel_compat.h` shims cv300 introduced) — coming next
  • OpenIPC/firmware (`hi3516cv200_neo_defconfig` + post-image script) — coming third; depends on this PR being mergeable so the upstream-patches tarball has the cv200 DT

Why now

cv200 was issue #46 in OpenIPC/openhisilicon — V2 has no OSAL layer, so historically it was locked to kernel 4.9. The blob struct-drift wall the issue called out (init_timer_key with `struct timer_list.data`) turns out to only affect the video pipeline blobs; everything below — kernel boot, network, userspace, audio — works fine on 7.0 with the right CRG + DT + shim plumbing. This PR lands the kernel side.

Vixand added 3 commits May 18, 2026 06:51
V2 generation (ARM926EJ-S, ARMv5TE) SoC family — Hi3516CV200,
Hi3518EV200, Hi3518EV201 — all share the same CRG layout at
0x20030000 and the same sysctrl block at 0x20050000. The vendor 4.9
BSP drove these via drivers/clk/hisilicon/clk-hi3518ev20x.c; port
the full clock topology onto the modern crg- platform_driver scaffold
that crg-hi3516cv300.c established for the V3 sibling.

Adds:

  - 25 fixed-rate roots (3 / 6 / 24 / 25 / 27 / 37.125 / 49.5 / 50 /
    54 / 74.25 / 99 / 125 / 148.5 / 198 / 200 / 250 / 297 / 300 /
    396 / 540 / 594 / 600 / 650 / 750 / 1188 MHz)
  - 5 muxes (uart/fmc/mmc0-1/eth)
  - 1 divider (sysapb)
  - 13 gates (uart0-3, spi0-1, fmc, mmc0-1, eth, dmac, usb2 utmi/hrst)
  - 4 sysctrl timer muxes registered via a separate provider

Two CLK_OF_DECLARE entries make TIMER/APB/UART/ETH available before
the platform_driver model is alive, so SP804 / PL011 / FEMAC don't
defer-forever or read clk_get_rate() == 0:

  - hisilicon,hi3518ev20x-sysctrl  → TIMER fixed-rate (3 MHz)
  - hisilicon,hi3518ev20x-clock    → sysapb / UART0-3 / ETH fixed-rate

The reset controller stays no-op but registers an explicit 2-cell
xlate so reset_controller_register doesn't force of_reset_n_cells = 1
(which had silently broken FEMAC on cv300 before that same fix —
this avoids the same trap on cv200).

dt-bindings/clock/hi3516cv200-clock.h is the matching clock-ID
header; the DT added in a later patch in this series references it
verbatim from cv200 + sibling boards.

Tested booting Linux 7.0 on a hi3516cv200 machine model under
qemu-hisilicon: SP804 ticks, FEMAC DHCP succeeds (10.0.2.15 / 10.0.2.2
via SLIRP), userspace reaches \`openipc-hi3516cv200 login:\`, no
Oops / panic / BUG / Trace.
Port the vendor 4.9 BSP hi3518ev20x DT to a 7.x-clean form and hook
the DEMB reference board into the hisilicon dtb Makefile. Same SoC
family as the vendor BSP (Hi3516CV200 / Hi3518EV200 / Hi3518EV201);
keep the vendor compatible strings ("hisilicon,hi3518ev20x-clock",
"-sysctrl") so the BSP DT remains drop-in compatible with this driver.

SoC dtsi (hi3516cv200.dtsi):

  - drop legacy skeleton.dtsi (removed upstream in 4.18)
  - SP804 dual_timer with explicit clock-frequency = <3000000>:
    sp804 driver reads clk_get_rate() during start_kernel; without
    the property it would see 0 and refuse to register
  - hisi-femac-mdio: clock-names = "mdio" (modern devm_clk_get(dev,
    "mdio") needs a named clock; older bindings tolerated nameless)
  - hisi_femac: hisilicon,phy-reset-delays-us = <10000 10000 30000>
    required by the modern femac driver when a "phy" reset is
    declared

DEMB board (hi3516cv200-demb.dts):

  - 64 MiB DDR @ 0x80000000 — matches production cv200 cameras that
    typically ship with 64 MiB total. The vendor mmz allocator is
    expected to claim the upper 32 MiB via `mmz=...` bootargs; the
    kernel uses 32 MiB.
  - bootargs configured for serial console + initrd handoff from
    U-Boot, matching the (future) cv200_neo firmware defconfig
  - phy@1 attached under &mdio with phy-mode = "mii"
  - i2c_bus0 / spi_bus0 / uart0 enabled for cv200 reference platforms

Tested under qemu-hisilicon -M hi3516cv200 with a minimal initramfs:
kernel boots through SP804 + PL011, mounts squashfs initrd, FEMAC
DHCP succeeds, ntpd syncs the wall clock, no console errors.

ARCH_HI3516CV200 is selected via the Kconfig change in the next
patch in this series.
Wire the V2 SoC family (Hi3516CV200 / Hi3518EV200 / Hi3518EV201) into
the hibvt platform choice. Selects:

  - ARM_VIC, ARM_TIMER_SP804  — interrupt + timer hardware
  - PINCTRL                   — required by hibvt pinctrl
  - COMMON_CLK_HI3516CV200    — the CRG driver added earlier in this
                                series
  - ARCH_HAS_RESET_CONTROLLER + RESET_CONTROLLER — femac resets

Depends on ARCH_MULTI_V5 (ARM926EJ-S, ARMv5TE) + CPU_LITTLE_ENDIAN
— matches the existing ARCH_HI3516CV300 sibling.

After this patch, the kernel boots end-to-end on the cv200 machine
model in qemu-hisilicon. Real hardware verification is gated on the
openhisilicon-side OSAL shim work that resolves blob-import gaps for
do_gettimeofday / register_sysctl_table / strlcpy on modern kernels
(separate openhisilicon PR, doesn't affect the kernel-side support
landing here).
@widgetii widgetii merged commit 8ace3d4 into upstream-patches May 18, 2026
widgetii added a commit to OpenIPC/openhisilicon that referenced this pull request May 22, 2026
…set (#170)

PRs #162 and #165 landed the initial V2/V2A bring-up shims based on the
issue #50 audit (4 symbols for cv200, 3 for av100). Exercising the
real firmware build for the first time (hi3516cv200_neo via the
upstream-patches 7.0 base) surfaced 8 more undefined symbols that
issue #50 missed — the audit only covered blob source-imports, not
the compiler-generated calls (memset → __memzero, kmalloc → __kmalloc
internal slowpath, etc.) and not the symbols pulled in via inline-
function expansion at blob-build time against the 4.9 kernel headers.

This commit extends both shims (V2 cv200 + V2A av100) to cover every
symbol modpost reports as undefined for the V2/V2A blob set on Linux
7.0. Verified empirically: hi3516cv200_neo now builds, boots in QEMU
to a login prompt, and meets the openipc/firmware QEMU DoD
(eth0 link, DHCP via SLIRP, ping 10.0.2.2). hi3516cv200_lite and
hi3516av100_lite (kernel 4.9 production targets) rebuilt against this
tree are byte-equivalent to nightly:

  - cv200_lite: 331/331 rootfs files, 68/68 hisilicon .ko, sets
    identical
  - av100_lite: 290/290 rootfs files, 61/61 hisilicon .ko, sets
    identical

kernel/compat/kernel_compat.h adds:

  - pte_offset_map(pmd, addr) -> pte_offset_kernel(...) on >= 6.5.
    Modern pte_offset_map() inlines to __pte_offset_map() which is
    NOT EXPORT_SYMBOL'd, so modules can't link it. pte_offset_kernel
    is a static inline over pmd_page_vaddr() + pte_index() — same
    user-page-table lookup the legacy code already did without
    locking. Source-side fix because the call is in our own
    cv200/av100 mmz-userdev usr_virt_to_phys, not the blob.

Both shim modules add the following exports (gated >= 5.0 so 4.9
lite stays a no-op shell):

   Symbol               Modern equivalent we forward to
   ──────────────────   ───────────────────────────────────────
   _cond_resched        __cond_resched
   __kmalloc            __kmalloc_noprof          (6.5+)
   kmem_cache_alloc     kmem_cache_alloc_noprof   (7.0 macro)
   __memzero            memset(ptr, 0, n)
   PDE_DATA             pde_data                  (5.17 rename)
   printk               vprintk via _printk       (6.0 rename)
   register_sysctl_paths register_sysctl_sz / register_sysctl
   jiffies_to_msecs     (MSEC_PER_SEC / HZ) * j   — header inline
   del_timer            timer_delete              (7.0 rename)
   vmalloc              vmalloc_noprof            (7.0 macro)
   dev_err              dev_vprintk_emit at KERN_ERR
   sched_setscheduler   sched_set_fifo / sched_set_normal — caller
                        priority is dropped (sched_set_fifo doesn't
                        accept one); SCHED_RR mapped to FIFO. Best-
                        effort for legacy blobs that just want
                        "raise above SCHED_NORMAL".

Two header-collision cases needed a Kbuild-level macro rename
(passed as -D... in CFLAGS_) so the static-inline definition in
<linux/sched.h> / <linux/jiffies.h> doesn't conflict with our
EXPORT_SYMBOL'd function under the same name:

  - _cond_resched         (static inline since 5.10 preempt-dynamic
                           rework; commit fe32d3cd5e8e)
  - jiffies_to_msecs      (static inline when HZ | MSEC_PER_SEC —
                           HZ=100 production config)

For the macro-style conflicts (kmem_cache_alloc, vmalloc, PDE_DATA,
printk, dev_err, del_timer) #undef in the shim source is sufficient.

Out of scope for this commit (still tracked in issue #51):

  - struct timer_list .data ABI drift (chnl/viu/vpss blobs) — the
    shim resolves init_timer_key but timers don't fire with the
    correct argument until the blob is recompiled. Documented in
    both shim sources. Surfaces as broken video pipeline on
    cv200_neo / av100_neo; not a load-time error.

  - hi3516av100 mainline DT / CRG — av100_neo firmware target is
    blocked on a separate openipc/linux PR (av100 has no mainline
    Kconfig / DT / clock-driver support yet, unlike cv200 which
    landed in OpenIPC/linux#43). cv200_neo unblocked.

Co-authored-by: Vasiliy Yakovlev <vixand@openipc.org>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
widgetii added a commit that referenced this pull request May 22, 2026
#44)

* arm: hisilicon: add hi3516av100 / hi3516dv100 SoC support (CRG + DT + Kconfig)

V2A generation (Cortex-A7, ARMv7) SoC family — Hi3516AV100 and the
pin-compatible Hi3516DV100. Same shape as the V2 cv200 / 3518ev20x
support landed in #43 except this one is ARMv7 with GIC + arch-timer
instead of VIC + SP804.

Adds:

  - drivers/clk/hisilicon/crg-hi3516av100.c (~330 lines): ported from
    the 4.9 vendor BSP clk-hi3516a.c onto the modern crg- platform_
    driver scaffold (mirroring crg-hi3516cv200.c).
      - 34 fixed-rate roots (3 / 6 / 13.5 / 24 / 25 / 27 / 37.125 / 50
        / 74.25 / 75 / 99 / 100 / 125 / 145 / 148.5 / 150 / 194 / 198
        / 200 / 229 / 237 / 242 / 250 / 297 / 300 / 333 / 400 / 500
        / 594 / 600 / 750 / 900 / 1000 / 1188 MHz)
      - APLL stub fixed-rate at 850 MHz (mid of vendor OPP table) —
        full PLL programming is a follow-up; the kernel boots fine
        with the U-Boot-configured CPU rate.
      - 9 muxes (sysaxi, snor, snand, nand, mmc0/1, uart, eth_phy, a7)
      - 1 fixed-factor (clk_sysapb = sysaxi_mux / 4)
      - 15 gates (snor/snand/nand, mmc0/1, usb utmi/hrst, uart0-3,
        eth + eth_macif, spi0-1, dmac)
      - CLK_OF_DECLARE early init for sysctrl timer slots (8 entries
        — av100 exposes TIME0_0..TIME3_7 vs cv200's 4) and early
        UART / ETH consumers needing clk_get during start_kernel
        before platform_driver probing.
      - Noop reset-controller with 2-cell xlate so higmac probe
        doesn't defer forever waiting for resets.

  - arch/arm/boot/dts/hisilicon/hi3516av100.dtsi (~290 lines):
      - GIC v2 at 0x20300000 (cortex-a7-gic).
      - Architected ARM generic timer (arm,armv7-timer) — av100 has
        Cortex-A7 generic timer; SP804 dual_timer is exposed but
        disabled by default and only board files can enable.
      - PL011 uart0-3, PL022 spi0/1, PL061 gpio0-3 (vendor BSP wires
        16 GPIO chips; mainline port enables 4 — sufficient for a
        DEMB board; rest can be added per-board).
      - hisi-i2c-hisilicon i2c_bus0-2, hisi-spi-nor controller.
      - higmac ethernet at 0x10090000 with MDIO sub-node — distinct
        from cv200/cv300's femac.
      - himci mmc0/1 at 0x206e0000/0x206f0000.
      - Skeleton.dtsi removed (4.18+ convention; explicit
        #address-cells/#size-cells on root).

  - arch/arm/boot/dts/hisilicon/hi3516av100-demb.dts (~95 lines):
      Reference board — 1 GiB RAM at 0x80000000, single Cortex-A7
      Linux CPU (vendor BSP layout, even though the SoC has 2 cores),
      UART0 console at 115200n8, higmac + MDIO ethphy@1 rgmii.

  - include/dt-bindings/clock/hi3516av100-clock.h: clock IDs.

  - arch/arm/mach-hibvt/Kconfig: ARCH_HI3516AV100 entry.
      depends on ARCH_MULTI_V7. selects HAVE_ARM_ARCH_TIMER, ARM_GIC,
      COMMON_CLK_HI3516AV100, ARCH_HAS_RESET_CONTROLLER. Note: does
      NOT select ARM_TIMER_SP804 because arch-timer is preferred on
      this SoC (Cortex-A7 generic timer).

  - drivers/clk/hisilicon/Kconfig: COMMON_CLK_HI3516AV100 entry.

  - drivers/clk/hisilicon/Makefile: register the new object.

  - arch/arm/boot/dts/hisilicon/Makefile: register the demb.dtb.

After this patch, the kernel boots end-to-end on an av100 board.
Real hardware verification is gated on the openhisilicon-side OSAL
shim work (#170 expanded the V2A blob-symbol set) and on a separate
firmware-side av100_neo defconfig — neither block landing this
kernel-side support.

Co-authored-by: Vasiliy Yakovlev <vixand@openipc.org>

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* net: hisilicon: add hisi_higmac driver for hi3516av100 GMAC

Minimal mainline platform driver for the higmac (Gigabit Ethernet MAC)
IP block used on Hi3516AV100 / Hi3516DV100. The vendor 4.9 BSP carries
a 3000-line driver in drivers/net/ethernet/hisilicon/higmac/ with TSO,
EEE, AVS, multicast filters, statistics, ethtool, PM, etc. This port
strips everything except the descriptor-ring TX/RX path that QEMU
emulates and that real hardware needs to boot — sufficient for ifup,
DHCP, and ping; production features can be layered on later.

Register layout follows the QEMU machine model
(qemu-hisilicon hw/net/hisi-gmac.c) which mirrors the vendor IP:

  0x0000 STATION_ADDR_LOW       MAC address
  0x0004 STATION_ADDR_HIGH
  0x0040 PORT_MODE              100M full hardcoded for QEMU
  0x0044 PORT_EN                bit1 RX_EN | bit2 TX_EN
  0x0064 REC_FILT_CONTROL       permissive (BIT_CRC_ERR_PASS)
  0x03C0 MDIO_SINGLE_CMD        embedded mii_bus
  0x03C4 MDIO_SINGLE_DATA
  0x0500 RX_FQ_* (free queue)   SW pushes empty buffers
  0x0520 RX_BQ_* (buffer queue) HW pushes received frames
  0x0580 TX_BQ_* (send queue)   SW pushes outgoing
  0x05A0 TX_RQ_* (reclaim queue) HW pushes completions
  0x05C0 RAW_PMU_INT            IRQ status (W1C)
  0x05C4 ENA_PMU_INT            IRQ mask
  0x05CC DESC_WR_RD_ENA         master DMA enable (0xF = all on)

Driver structure mirrors hisi_femac.c — platform_driver, single
NAPI instance (weight 64), devm clk/reset acquisition,
of_phy_get_and_connect via embedded mdio sub-node, dma_alloc_coherent
ring memory. MDIO is at offset 0x3c0 of the same MMIO region as the
MAC (vendor used a separate hisilicon,hisi-gemac-mdio platform device
for this; mainline registers the mii_bus inline since the MMIO range
is contiguous).

DT bindings:

  reg                — single MAC MMIO range
  interrupts         — combined IRQ
  clocks/clock-names — "higmac_clk" + "macif_clk" (both optional)
  resets/reset-names — "port_reset" + "macif_reset" (both optional)
  phy-handle         — reference to mdio child's PHY node
  phy-mode           — "rgmii" / "mii" / "rmii"
  mac-address        — from DT or random fallback

DTSI delta: drops the separate hisilicon,hisi-gemac-mdio node and
folds an mdio sub-node into the higmac itself; the demb.dts moves the
ethphy@1 into that sub-node. Matches the mainline-friendly layout for
GMAC + MDIO sharing one MMIO range.

Out of scope (vendor driver has, mainline port doesn't):

  - TSO / GSO / GRO (NAPI uses napi_gro_receive so GRO works
    transparently — no driver-side TSO).
  - COE checksum offload bits (TSO_COE_CTRL register).
  - EEE / autoEEE (separate vendor sub-directory).
  - AVS (adaptive voltage scaling).
  - Statistics / ethtool / WoL / coalescing tuning.
  - Multicast hash table — driver runs permissive (broadcast + multicast
    pass; effectively promiscuous in steady state). Filter tightening
    would be a follow-up.
  - PM suspend/resume — leaves the IP at HW defaults across suspend.

Verified clean compile under `make W=1` against Linux 7.0, ARM target,
OpenIPC toolchain. Real-hardware verification is gated on the
hi3516av100_neo firmware-side bring-up (separate openipc/firmware
PR), which uses this driver and validates QEMU smoke + login + ping.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Vasiliy Yakovlev <vixand@openipc.org>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants